#pragma once

#include <vector>

using namespace std;

template<class Key>
class PriorityQueue {
public:
	class Vertex;
	PriorityQueue() : numberOfVertex_(0), headVertex_(nullptr) {}
	~PriorityQueue();
	Vertex* insert(Key newKey);
	Vertex* insert(Vertex* newVertex);
	Vertex* getMax();
	Vertex* extractMax();
	bool increaseKey(Vertex* currentVertex, Key newKey);

private:
	class Vertex {
	public:
		Vertex() : key(Key()), mark(false), parent(nullptr),
			child(nullptr), prev(nullptr), next(nullptr), numberOfChildren(0) {}
		Vertex(Key newKey) : key(newKey), 
			mark(false), parent(nullptr), child(nullptr), 
			prev(nullptr), next(nullptr), numberOfChildren(0) {}
		Key key;
		bool mark;
		Vertex* parent;
		Vertex* child;
		Vertex* prev;
		Vertex* next;
		int numberOfChildren;
	};

	Vertex* headVertex_;
	int numberOfVertex_;

	void REQURSIVE_DELETE(Vertex* x);
	void FIB_LINK(Vertex* x, Vertex* y);
	void CONSOLIDATE();
	void CUT(Vertex* x, Vertex* y);
	void CASCADING_CUT(Vertex* x);
};

struct myTuple {
public:
	myTuple() :
		timeOfEnding(-1), numberOfLot(-1),
		valueOfStake(-1), timeOfStake(-1), betId(-1) {}

	myTuple(int a, int b, int c, int d, int e) :
		timeOfEnding(a), numberOfLot(b),
		valueOfStake(c), timeOfStake(d), betId(e) {}
	bool operator<(myTuple& other) {
		if (timeOfEnding != other.timeOfEnding)
			return timeOfEnding < other.timeOfEnding;
		if (numberOfLot != other.numberOfLot)
			return numberOfLot < other.numberOfLot;
		if (valueOfStake != other.valueOfStake)
			return valueOfStake < other.valueOfStake;
		if (timeOfStake != other.timeOfStake)
			return timeOfStake < other.timeOfStake;
		if (betId != other.betId)
			return betId < other.betId;
		return false;
	}
	bool operator>(myTuple& other) {
		if (timeOfEnding != other.timeOfEnding)
			return timeOfEnding > other.timeOfEnding;
		if (numberOfLot != other.numberOfLot)
			return numberOfLot > other.numberOfLot;
		if (valueOfStake != other.valueOfStake)
			return valueOfStake > other.valueOfStake;
		if (timeOfStake != other.timeOfStake)
			return timeOfStake > other.timeOfStake;
		if (betId != other.betId)
			return betId > other.betId;
		return false;
	}
	int timeOfEnding;
	int numberOfLot;
	int valueOfStake;
	int timeOfStake;
	int betId;
};

typedef PriorityQueue<myTuple>::Vertex* bet;
